package org.spbsu.apco.server.taskset;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spbsu.apco.common.Pair;
import org.spbsu.apco.server.broker.Broker;
import org.springframework.beans.factory.annotation.Required;

import java.util.*;

/**
 * User: solozobov
 * Date: 20.11.12
 */

public class TaskSetEmitter {
    private static final Logger LOG = LoggerFactory.getLogger(TaskSetEmitter.class);

    private LinkedList<Pair<Integer, BaseTaskSet>> taskSet2time;

    private Broker broker;

    public void start() {
        final Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                int time = 0;
                Set<BaseTaskSet> sent = new HashSet<BaseTaskSet>();
                while (!taskSet2time.isEmpty()) {
                    final Pair<Integer, BaseTaskSet> pair = taskSet2time.remove();
                    try {
                        Thread.sleep(pair.first - time);
                    } catch (InterruptedException e) {
                        LOG.error("TaskSetEmitter woke up in a sweat", e);
                    }
                    time = pair.first;
                    broker.addTaskSet(pair.second);
                    sent.add(pair.second);
                }
                while (!sent.isEmpty()) {
                    for (BaseTaskSet baseTaskSet : new HashSet<BaseTaskSet>(sent)) {
                        if (broker.isFinished(baseTaskSet)) {
                            LOG.info("TaskSet #{} finished!", new Object[]{baseTaskSet.getId()});
                            LOG.info(broker.getResults(baseTaskSet).toString());
                            sent.remove(baseTaskSet);
                        }
                    }
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        LOG.warn("Interrupted", e);
                    }
                }
            }
        });
        thread.setDaemon(true);
        thread.start();
    }

    @Required
    public void setTime2TaskSet(final Map<Integer, BaseTaskSet> taskSet2time) {
        final LinkedList<Pair<Integer, BaseTaskSet>> result = new LinkedList<Pair<Integer, BaseTaskSet>>();
        for (final Integer time : taskSet2time.keySet()) {
            result.add(Pair.of(time, taskSet2time.get(time)));
        }
        Collections.sort(result, new Comparator<Pair<Integer, BaseTaskSet>>() {
            @Override
            public int compare(Pair<Integer, BaseTaskSet> p1, Pair<Integer, BaseTaskSet> p2) {
                return p1.first - p2.first;
            }
        });

        this.taskSet2time = result;
    }

    public void setBroker(final Broker broker) {
        this.broker = broker;
    }
}
